Next.js入門 3 getStaticPropsとgetStaticPathsによるSSG
Next.jsがReact.jsのコンポーネントを置くだけでいい感じにページとしてルーティングしてくれるだけではなく、APIから動的にデータを取得して表示する仕組みや、React.jsコンポーネントを事前にビルドしてキャッシュすることで高速化する仕組みを持っていることについて理解していきましょう
React.jsのコンポーネントをHTMLレンダリング結果やJSONとして事前に生成してしまっておいて、それを読み込むだけにすれば、React.jsで構築されたWebサイトは、通常の静的サイト以上に読み込みや画面遷移が速くなるという発想が静的サイト生成(スタティックサイトジェネレーション)(SSG)
Next.jsには、静的サイト生成のための、ビルドという概念がある
Next.jsにおけるビルドとは、Next.jsが認識できるpages/以下のルーティング対象であるすべてのページを、事前に生成してキャッシュしておくということ
Next.jsにおけるビルドの方法
code:bash
npm run build
と実行することで、pages/以下のtsxファイルが.next/server/pagesというディレクトリに生成される
code:bash
npm start
と実行することで、生成したキャッシュを元にした本番用サーバーが立ち上がる
これまで実行していたnpm run devは、あくまでも開発用サーバー
あとで実際に作業するのでこの時点では開発用サーバーを動かしたままにしておいてください
getStaticPropsによる静的サイト生成
Next.jsの重要なルール:pages/以下にあるファイルでgetStaticPropsという関数をexportすると、React.jsコンポーネントのレンダリング前にその関数が実行されて、結果がReact.jsコンポーネントに渡される
以降はVSCodeでの作業です
pagesにcovid19ディレクトリを作ります
pages/covid19/index.tsxファイルを作ります
以下をコピペします
code:pages/covid19/index.tsx
import Link from "next/link"
const Page = ({ data }:any) => {
return (
<div>
<ul>
{data.map((item:any) => {
return (
<li>
<Link href={/covid19/${item.pref}}>
<a>
{item.pref}
</a>
</Link>
</li>
)
})}
</ul>
</div>
)
};
export default Page;
export async function getStaticProps() {
const data = await res.json();
return { props: { data } };
};
重要な点
export async function getStaticProps() {という部分
pages/以下にあるファイルにgetStaticPropsという名前の関数があると、Next.jsはReact.jsのコンポーネントをレンダリングする前にgetStaticProps関数を実行して、その返り値をReact.jsコンポーネントにpropsとして渡します
メモ
Typescriptを使っているのに{ data }:anyとかitem:anyとかやっているのは良くない作法です
勉強中なので雑にしていますが、ちゃんと開発する際にはちゃんと型を記述するべき
以降はブラウザでの作業です
https://gyazo.com/d131fbb61b2a348df4a72074d2ab5676
こういう画面が表示されるはずです!!
getStaticPathsによる、ダイナミックルーティングの静的サイト生成
Next.jsの重要なルール:pages/以下にあるダイナミックルーティングを含むファイルでgetStaticPathsという関数をexportすると、Next.jsのビルド時にその関数が実行されて、そこで指定されたパスがすべて事前にビルドされキャッシュされる
以降はVSCodeでの作業です
pagesにcovid19ディレクトリを作ります
pages/covid19/[pref].tsxファイルを作ります
以下をコピペします
code:pages/covid19/pref.tsx import Link from "next/link"
const Page = ({ data }:any) => {
return (
<div>
<h1>{data.itemList0.name_jp}の新型コロナウイルス感染者数</h1> <Link href='/covid19'><a>戻る</a></Link>
<ul>
{data.itemList.map((item:any) => {
return (
<li>
{item.date}: {item.npatients}
</li>
)
})}
</ul>
</div>
)
};
export default Page;
export async function getStaticPaths() {
const json = await res.json();
const paths = json.map((data:any) => ({
params: { pref: data.pref }
}));
return { paths, fallback: false };
};
export async function getStaticProps({ params }:any) {
const res = await fetch(https://opendata.corona.go.jp/api/Covid19JapanAll?dataName=${encodeURIComponent(params.pref)});
const data = await res.json();
return { props: { data } };
};
重要な点
export async function getStaticPaths() {という部分
pages/以下に、[id].tsxのようなダイナミックルーティングのファイルがあり、かつそのファイルにgetStaticPathsという名前のファイルがあると、Next.jsはビルド時にgetStaticPaths関数を実行して、そこから得られるすべてのパスを対象として事前にHTML・JSONファイルとして生成します
ここでは、都道府県の一覧をパスとして返しているので、47都道府県のパスを対象として静的生成が行われます
メモ
このサンプルもanyだらけなので本当は良くない
以降はブラウザでの作業です
https://gyazo.com/77698f4792a1d41614ab23534913e374
こういうページが表示されるはずです!!
この時点で戻るボタンをクリックしたり都道府県をクリックしたりして、画面遷移の速さを確認しておいてください
https://gyazo.com/31f64ae7ecdc2573f7c86f1d56268201
ややモッサリしていることが感じられると思います
Next.jsによる静的サイト生成の実践
せっかくgetStaticPropsやgetStaticPathsを実装したので、Next.jsによる静的サイト生成を試してみましょう
以降はターミナル内での作業です
npm run devで起動し続けている開発サーバーを一旦停止する
停止するためにはキーボードでctrl+cを押します
Next.jsのビルドを実行する
code:bash
npm run build
https://gyazo.com/6e64b7711ad2f1308cc60a57dd4ffdef
こういう出力になるはずです!!
この時点で.next/server/pages/covid19というディレクトリを確認してみると
https://gyazo.com/90d44863ec80b8bb66d886109bdbef5f
こういうことになっています
これがNext.jsの静的サイト生成のからくりというわけです
Next.jsの本番用サーバーを立ち上げてみましょう
code:bash
npm start
以降はブラウザでの作業です
https://gyazo.com/85e3bdab6c92cf283229f0761e9677c3
都道府県をクリックしたり戻るをクリックしたりして行ったり来たりしてみましょう
画面遷移が異常に速いことが体感できると思います
ここまでで、Next.jsでAPIのデータを元に動的にページを生成する方法が理解できたと思います
Next.jsの公式ドキュメント(日本語訳)
データ取得
ページから getStaticProps という async 関数をエクスポートすると、Next.js はビルド時に getStaticProps から返される props を使ってプリレンダリングします。
ページが動的ルート(ドキュメント)を持ち、getStaticPropsを使用する場合、ビルド時に HTML をレンダリングするためのパス一覧を定義する必要があります。
動的ルートを使ったページから getStaticPaths という async 関数をエクスポートすると Next.js は getStaticPaths で指定された全パスを静的にプリレンダリングします。